﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WebApi.Core.Model;

namespace WebApi.Core.Common
{   
    public static class PredicateExtensions
    {
        //示例   链式调用 
        //var condition1 = (User x) => x.Age > 18;   // 条件1：年龄大于18 
        //var condition2 = (User x) => x.City == "北京";  // 条件2：所在城市为北京 
        //var condition3 = (User x) => x.RegisterTime > new DateTime(2023, 1, 1);  // 条件3：注册时间在2023年后 

        //var finalCondition = condition1.And(condition2).And(condition3);   // 链式组合

        //var conditionA = (User x) => x.UserName.Contains("张"); // 条件1：用户名包含"张"  
        //var conditionB = (User x) => x.Phone.StartsWith("138");   // 条件2：手机号以138开头 
        //var conditionC = (User x) => x.RegisterTime > new DateTime(2023, 1, 1);   // 条件3：注册时间在2023年后 
        //var conditionD = (User x) => x.LoginCount > 100;  // 条件4：登录次数大于100 

        //var finalCondition = conditionA.Or(conditionB)  // A || B      // 链式组合逻辑：(A OR B) AND (C OR D)
        //                         .And(conditionC.Or(conditionD)); // && (C || D)

        /// <summary>
        /// AND 条件组合
        /// </summary>
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,Expression<Func<T, bool>> expr2)
        {
            // 统一参数
            var parameter = Expression.Parameter(typeof(T));
            // 替换表达式参数
            var left = ReplaceParameter(expr1, parameter);
            var right = ReplaceParameter(expr2, parameter);

            // 组合 AND 条件
            var body = Expression.AndAlso(left, right);

            return Expression.Lambda<Func<T, bool>>(body, parameter);
        }

        /// <summary>
        /// OR 条件组合（健壮型）
        /// </summary>
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,Expression<Func<T, bool>> expr2)
        {
            var parameter = Expression.Parameter(typeof(T));

            var left = ReplaceParameter(expr1, parameter);
            var right = ReplaceParameter(expr2, parameter);

            var body = Expression.OrElse(left, right);

            return Expression.Lambda<Func<T, bool>>(body, parameter);
        }

        /// <summary>
        /// 替换表达式参数
        /// </summary>
        private static Expression ReplaceParameter<T>(Expression<Func<T, bool>> expr,ParameterExpression newParameter)
        {
            var visitor = new ReplaceExpressionVisitor(expr.Parameters[0], newParameter);
            return visitor.Visit(expr.Body);
        }

        /// <summary>
        /// 表达式参数替换访问器
        /// </summary>
        private class ReplaceExpressionVisitor : ExpressionVisitor
        {
            private readonly Expression _oldValue;
            private readonly Expression _newValue;

            public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
            {
                _oldValue = oldValue;
                _newValue = newValue;
            }

            public override Expression Visit(Expression node)
            {
                return node == _oldValue ? _newValue : base.Visit(node);
            }
        }


    }
}
